// fetchWorkingDays.js
// 第1版（已废弃）

/*
==============================================
  计算说明
==============================================
  当日21点至次日9点有记录，计当日夜餐
==============================================
  当日0点至次日0点有记录: 计当日远郊
  当日21点至次日0点有记录: 计次日远郊
==============================================
  当日打卡跨度小于4H: 
    且前日18点后有记录: 计1天
    否则: 计0.5天
  当日打卡跨度大于4H: 计1天
==============================================
  seat table 数据格式
==============================================
  {
    "userName": "殷茂鑫",
    "startTime": "2024-01-23 18:33:51",
    "endTime": null,
    "seatCode": "SUP02",
    "seatRole": "管制",
    "seatPost": "带班主任岗"
  }
==============================================
  report table 数据格式
==============================================
  {
    "name": "钱坤",
    "seat": "SUP02",
    "post": "带班主任岗",
    "role": "管制",
    "begin": "2023-12-31 23:06:57",
    "end": "2024-01-01 03:03:39",
    "hours": 3.97
  }
==============================================
*/

import dayjs from "dayjs";

// 夜班起止时间, 用于修正夜餐计算时间
const nightRange = {
  startHour: 22,
  startMinute: 0,
  endHour: 9,
  endMinute: 30,
};

// 此参数已作废
// const eveningHour = 21; // 夜班时段的起点
// const morningHour = 9; //  夜班时段的终点

// 此函数已作废
// const mathTheDay = (begTime, endTime, offsetDay = 0, toString = true) => {
//   // 该方法用于确定 "当日" 指的是哪一天
//   let result = dayjs();
//   if (begTime.isSame(endTime, "day")) {
//     // 上下席位日期为同一天
//     if (begTime.hour < morningHour) {
//       // 上席位时间在 "morningHour" 以前, 返回前一天的日期
//       result = dayjs(
//         begTime.subtract(1, "day").format("YYYY-MM-DD" + " 00:00:00")
//       );
//     } else {
//       // 否则返回起始时间的日期
//       result = dayjs(begTime.format("YYYY-MM-DD" + " 00:00:00"));
//     }
//   } else {
//     // 上下席位日期不同, 返回起始时间的日期
//     result = dayjs(begTime.format("YYYY-MM-DD" + " 00:00:00"));
//   }
//   // 偏移指定天数
//   if (offsetDay > 0) {
//     result = result.add(offsetDay, "day");
//   } else if (offsetDay < 0) {
//     result = result.subtract(-offsetDay, "day");
//   }
//   // 返回 dayjs 对象 或 "YYYY-MM-DD" 格式的字符串
//   // 默认返回字符串
//   if (result && toString) {
//     return result.format("YYYY-MM-DD");
//   } else {
//     return result;
//   }
// };

export default function (data, dateRange, holidays = []) {
  // console.log("fetchWorkingDays", dateRange, data);
  if (!data || data.length == 0) {
    return null;
  }
  let result = {};
  let rangeStart = dayjs(dateRange[0]).hour(0).minute(0).second(0);
  let rangeEnd = dayjs(dateRange[1]).hour(23).minute(59).second(59);
  for (let i = 0; i < data.length; i++) {
    // 数据单元
    let cell = data[i];

    let uid = cell.userName;

    if (!result[uid]) {
      // 如果不存在 key 为 userName 的项目, 新建一条人员信息
      result[uid] = {
        name: uid,
        uid: cell.userId,
        hours: 0, // 总小时
        details: new Array(), // 打卡明细
        commutingDays: 0, // 远郊天数
        commutingDates: new Array(), // 远郊日期
        overnightDays: 0, // 夜餐天数
        overnightDates: new Array(), // 夜餐日期
        workingDays: 0, // 工作天数
        overtimeDays: 0, // 加班天数
        workingDates: {}, // 用于统计每日工作时长
        /*
        {
          wd20240201:{
            date: String,
            from: String,
            to: String,
            duration: Number,
            days: Number,
            type: Number,
          }
        }
        */
      };
    }

    // 人员目标
    let target = result[uid];
    let begTime = dayjs(cell.startTime);
    let endTime = cell.endTime ? dayjs(cell.endTime) : dayjs();

    // 时长
    // let duration = endTime.diff(begTime);

    // 有效时长: 在统计范围内的席位时间
    let isEndTimeInRange = endTime.isBefore(rangeEnd);
    let isBegTimeInRange = begTime.isAfter(rangeStart);
    let effectiveEndTime = isEndTimeInRange ? endTime : rangeEnd;
    let effectiveBegTime = isBegTimeInRange ? begTime : rangeStart;
    let effectiveDuration = effectiveEndTime.diff(
      effectiveBegTime,
      "hour",
      true
    );
    effectiveDuration = effectiveDuration > 0 ? effectiveDuration : 0;
    // if (effectiveDuration < 0) {
    //   console.log(
    //     "fetchWorkingDays",
    //     "effectiveDuration",
    //     effectiveDuration,
    //     "begTime",
    //     begTime.format("YYYY-MM-DD HH:mm:ss"),
    //     "endTime",
    //     endTime.format("YYYY-MM-DD HH:mm:ss"),
    //     "rangeStart",
    //     rangeStart.format("YYYY-MM-DD HH:mm:ss"),
    //     "rangeEnd",
    //     rangeEnd.format("YYYY-MM-DD HH:mm:ss"),
    //     "isBegTimeInRange",
    //     isBegTimeInRange,
    //     "isEndTimeInRange",
    //     isEndTimeInRange,
    //     "effectiveBegTime",
    //     effectiveBegTime.format("YYYY-MM-DD HH:mm:ss"),
    //     "effectiveEndTime",
    //     effectiveEndTime.format("YYYY-MM-DD HH:mm:ss")
    //   );
    // } else {
    //   console.log("fetchWorkingDays", "effectiveDuration", "OK");
    // }

    // 累加总时长 (有效时长)
    target.hours += effectiveDuration;

    // 计入详情
    // target.details.push(cell);

    // 探测条件1:
    // 当日 "eveningHour" 点至次日 "morningHour" 有记录，计当日夜餐
    // if (endTime.hour() >= eveningHour || begTime.hour() <= morningHour) {
    //   let theDay = mathTheDay(begTime, endTime);
    //   if (!target.overnightDates.includes(theDay)) {
    //     target.overnightDates.push(theDay);
    //     target.overnightDays++;
    //   }
    // }

    // 探测条件2:
    // 当日 "任意时间" 有记录: 计当日远郊
    // 当日 "eveningHour" 以后有记录: 计次日远郊

    // if (true) {
    //   let theDay = mathTheDay(begTime, begTime);
    //   if (!target.commutingDates.includes(theDay)) {
    //     target.commutingDates.push(theDay);
    //     target.commutingDays++;
    //   }
    // }
    // if (true) {
    //   let theDay = mathTheDay(endTime, endTime);
    //   if (!target.commutingDates.includes(theDay)) {
    //     target.commutingDates.push(theDay);
    //     target.commutingDays++;
    //   }
    // }
    // if (endTime.hour() >= eveningHour || begTime.hour() >= eveningHour) {
    //   let theDay = mathTheDay(begTime, endTime, 1);
    //   if (!target.commutingDates.includes(theDay)) {
    //     target.commutingDates.push(theDay);
    //     target.commutingDays++;
    //   }
    // }

    // 探测条件1+2 (REV1):
    // 当日 "nightRange.startHour" 以后有记录，计当日夜餐
    // 次日 "nightRange.endHour" 以前有记录，计前日夜餐

    let isNight = false; // 是否有当日夜餐
    let isYest = false; // 是否有前日夜餐
    let isCross = false; // 是否有次日远郊

    if (begTime.isBefore(endTime, "day")) {
      // 跨日一定有当日夜餐
      // 跨日一定有次日远郊
      isNight = true;
      isCross = true;
    } else if (
      endTime.hour() >= nightRange.startHour &&
      endTime.minute() >= nightRange.startMinute
    ) {
      // 结束时间在 nightRange.start 以前有当日夜餐
      // 结束时间在 nightRange.start 以前有次日远郊
      isCross = true;
      isNight = true;
    } else if (
      begTime.hour() <= nightRange.endHour &&
      begTime.minute() <= nightRange.endMinute
    ) {
      // 开始时间在 nightRange.end 以前有前日夜餐
      isNight = true;
      isYest = true;
    }

    if (isNight) {
      let theDay = isYest
        ? begTime.subtract(1, "day").format("YYYY-MM-DD")
        : begTime.format("YYYY-MM-DD");
      if (!target.overnightDates.includes(theDay)) {
        target.overnightDates.push(theDay);
        target.overnightDays++;
      }
    }

    // 打卡当日一定有远郊
    let currentDay = begTime.format("YYYY-MM-DD");
    if (!target.commutingDates.includes(currentDay)) {
      target.commutingDates.push(currentDay);
      target.commutingDays++;
    }
    if (isCross) {
      // 如果次日有远郊
      let nextDay = begTime.add(1, "day").format("YYYY-MM-DD");
      if (!target.commutingDates.includes(nextDay)) {
        target.commutingDates.push(nextDay);
        target.commutingDays++;
      }
    }

    // 探测条件3:
    // 当日打卡跨度小于4H:
    //   且前日18点后有记录: 计1天
    //   否则: 计0.5天
    // 当日打卡跨度大于4H: 计1天

    let begDayIdent = "wd" + begTime.format("YYYYMMDD");
    let endDayIdent = "wd" + endTime.format("YYYYMMDD");
    // let isCrossDate = begDayIdent != endDayIdent;
    let isCrossDate = !endTime.isSame(begTime, "day");
    if (!target.workingDates[begDayIdent]) {
      // 如果不存在上席位日期对应的元素, 则新建元素, 起始/结束 时间为当前 cell 的起止时间
      target.workingDates[begDayIdent] = {
        date: begTime.format("YYYY-MM-DD"),
        from: begTime.format("YYYY-MM-DD HH:mm:ss"),
        to: isCrossDate
          ? begTime.format("YYYY-MM-DD") + " 23:59:59"
          : endTime.format("YYYY-MM-DD HH:mm:ss"),
        // 如果跨日期, 则结束时间为上席位日期的 23:59:59, 否则即为下席位时间
        duration: 0,
        days: 0.5,
        type: 0,
      };
    } else {
      // 已经存在上席位日期对应的元素
      if (begTime.isBefore(target.workingDates[begDayIdent].from, "minute")) {
        target.workingDates[begDayIdent].from = begTime.format(
          "YYYY-MM-DD HH:mm:ss"
        );
      }
      if (isCrossDate) {
        target.workingDates[begDayIdent].to =
          begTime.format("YYYY-MM-DD") + " 23:59:59";
      } else if (
        endTime.isAfter(target.workingDates[begDayIdent].to, "minute")
      ) {
        target.workingDates[begDayIdent].to = endTime.format(
          "YYYY-MM-DD HH:mm:ss"
        );
      }
    }
    // 修改起始日期对应元素的 duration
    // 也可以在二次遍历时进行计算, 以提高计算速度
    target.workingDates[begDayIdent].duration = dayjs(
      target.workingDates[begDayIdent].to
    ).diff(target.workingDates[begDayIdent].from, "hour", true);
    // console.log("test", i, target);
    // 跨度大于4小时, 则执勤时间为1天
    if (target.workingDates[begDayIdent].duration > 4) {
      target.workingDates[begDayIdent].days = 1;
    }
    // 跨日期的情况, 修改次日对应元素的内容
    if (isCrossDate) {
      // 如果不存在下席位日期对应的元素, 新建元素
      if (!target.workingDates[endDayIdent]) {
        target.workingDates[endDayIdent] = {
          date: endTime.format("YYYY-MM-DD"),
          from: endTime.format("YYYY-MM-DD") + " 00:00:00", // 起始时间为结束时间当日0点
          to: endTime.format("YYYY-MM-DD HH:mm:ss"), // 结束时间为下席位时间
          duration: 0,
          days: 0.5,
          type: 0,
        };
      } else {
        // 已经存在下席位日期对应的元素
        target.workingDates[endDayIdent].from =
          endTime.format("YYYY-MM-DD") + " 00:00:00";
        if (endTime.isAfter(target.workingDates[endDayIdent].to, "minute")) {
          target.workingDates[endDayIdent].to = endTime.format(
            "YYYY-MM-DD HH:mm:ss"
          );
        }
      }
      // 跨日期的情况, 修改下席位日期对应元素的 duration
      // 也可以在二次遍历时进行计算, 以提高计算速度
      target.workingDates[endDayIdent].duration = dayjs(
        target.workingDates[endDayIdent].to
      ).diff(target.workingDates[endDayIdent].from, "hour", true);
      // 跨度大于4小时, 则执勤时间为1天
      if (target.workingDates[endDayIdent].duration > 4) {
        target.workingDates[endDayIdent].days = 1;
      }
    }
  }

  // 二次遍历: 将 Object 转换为 Array, 统计工作天数/加班天数
  let finalResult = Object.keys(result).map((key) => {
    // let workingDays = 0;
    // let overtimeDays = 0;
    let workingDates = Object.keys(result[key].workingDates)
      .map((wdk) => {
        let inRange =
          rangeStart.isSameOrBefore(
            result[key].workingDates[wdk].date,
            "day"
          ) &&
          rangeEnd.isSameOrAfter(result[key].workingDates[wdk].date, "day");
        // workingDays += inRange ? result[key].workingDates[wdk].days : 0;
        let isHoliday = holidays.includes(result[key].workingDates[wdk].date);
        // overtimeDays +=
        //   isHoliday && inRange ? result[key].workingDates[wdk].days : 0;
        return {
          date: result[key].workingDates[wdk].date,
          from: result[key].workingDates[wdk].from,
          to: result[key].workingDates[wdk].to,
          duration: result[key].workingDates[wdk].duration,
          days: inRange ? result[key].workingDates[wdk].days : 0,
          type: isHoliday ? 1 : 0,
        };
      })
      .filter((item) => item.days > 0);
    let commutingDates = result[key].commutingDates.filter(
      (dateString) =>
        rangeStart.isSameOrBefore(dateString, "day") &&
        rangeEnd.isSameOrAfter(dateString, "day")
    );
    let overnightDates = result[key].overnightDates.filter(
      (dateString) =>
        rangeStart.isSameOrBefore(dateString, "day") &&
        rangeEnd.isSameOrAfter(dateString, "day")
    );
    let overtimeDates = workingDates.filter((element) => element.type == 1);
    return {
      name: result[key].name,
      uid: result[key].uid,
      hours: Math.round(result[key].hours * 100) / 100,
      commutingDates,
      commutingDays: commutingDates.length,
      overnightDates,
      overnightDays: overnightDates.length,
      workingDates,
      workingDays: workingDates.length,
      overtimeDates,
      overtimeDays: overtimeDates.length,
    };
  });
  console.log("fetchWorkingDays", finalResult);
  return finalResult;
}
